package com.pipayshop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pipayshop.entity.AccountInfo;
import com.pipayshop.entity.vo.AccountInfoVO;
import com.pipayshop.exception.BusinessException;
import com.pipayshop.mapper.UserAccountInfoMapper;
import com.pipayshop.service.UserAccountInfoService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.logging.Logger;

/**
 * <p>
 * 用户账户表 服务实现类
 * </p>
 *
 * @author nws
 * @since 2023-07-25
 */
@Service
public class UserAccountInfoServiceImpl extends ServiceImpl<UserAccountInfoMapper, AccountInfo> implements UserAccountInfoService {

    private final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);

    @Resource
    private UserAccountInfoMapper accountInfoMapper;

    /**
     * 根据用户Id查找用户账户表的积分余额和pi币余额
     */
    @Override
    public AccountInfoVO selectAccountById(String uid) {
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("invalid_parameter");
        }
        return accountInfoMapper.selectAccountInfo(uid);
    }

    @Override
    public BigDecimal selectAccountBalance(String uid) {
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("invalid_parameter");
        }
        return accountInfoMapper.selectAccountBalance(uid);
    }

    @Override
    @Transactional
    public Boolean addAccount(String uid, BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("amount_must_be_greater_than_zero");
        }
        AccountInfoVO accountInfoVO = accountInfoMapper.selectAccountInfo(uid);
        if (accountInfoVO == null){
            throw new BusinessException("用户不存在");
        }
        //用户增加余额
        int update = accountInfoMapper.update(null, new LambdaUpdateWrapper<AccountInfo>()
                .eq(AccountInfo::getUid, uid)
                .setSql("point_balance = point_balance + " + amount)
                .setSql("available_balance = available_balance +" + amount)
                .set(AccountInfo::getUpdateTime, new Date()));
        if (update <= 0) {
            throw new BusinessException("user_balance_increase_failed");
        }
        return true;
    }

    @Override
    public Boolean addPiAccount(String uid, BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("amount_must_be_greater_than_zero");
        }
        AccountInfoVO accountInfoVO = accountInfoMapper.selectAccountInfo(uid);
        if (accountInfoVO == null){
            throw new BusinessException("用户不存在");
        }
        //用户增加余额
        int update = accountInfoMapper.update(null, new LambdaUpdateWrapper<AccountInfo>()
                .eq(AccountInfo::getUid, uid)
                .setSql("pi_balance=pi_balance+" + amount)
                .set(AccountInfo::getUpdateTime, new Date()));
        if (update <= 0) {
            throw new BusinessException("increase_pi_balance_failed");
        }
        return true;
    }

    @Override
    @Transactional
    public Boolean reduceAccount(String uid, BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("amount_must_be_greater_than_zero");
        }
        // 获取商户积分余额
        AccountInfoVO accountInfoVO = accountInfoMapper.selectAccountInfo(uid);
        if (accountInfoVO == null){
            throw new BusinessException("用户不存在");
        }
        if (accountInfoVO.getAvailableBalance().compareTo(amount) < 0) {
            throw new BusinessException("insufficient_balance");
        }
        //用户减少余额
        int update1 = accountInfoMapper.update(null, new UpdateWrapper<AccountInfo>()
                .eq("uid", uid)
                .setSql("point_balance = point_balance - " + amount)
                .setSql("available_balance = available_balance -" + amount)
                .set("update_time", new Date()));
        if (update1 <= 0) {
            throw new BusinessException("减少余额失败");
        }
        return true;
    }

    @Override
    @Transactional
    public Boolean freezePoints(String uid, BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("amount_must_be_greater_than_zero");
        }
        AccountInfoVO traderAccountInfoVO = accountInfoMapper.selectAccountInfo(uid);
        if (traderAccountInfoVO == null){
            throw new BusinessException("用户不存在");
        }
        BigDecimal availableBalance = traderAccountInfoVO.getAvailableBalance();
        if (availableBalance.compareTo(amount) < 0) {
            throw new BusinessException("insufficient_balance");
        }
        //用户减少余额
        int update = accountInfoMapper.update(null, new LambdaUpdateWrapper<AccountInfo>()
                .eq(AccountInfo::getUid, uid)
                .setSql("available_balance = available_balance - " + amount)
                .setSql("frozen_balance = frozen_balance + " + amount)
                .set(AccountInfo::getUpdateTime, new Date()));
        if (update <= 0) {
            throw new BusinessException("points_freezing_failed");
        }
        return true;
    }

    @Override
    @Transactional
    public BigDecimal removeFrozen(String uid, BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("amount_must_be_greater_than_zero");
        }
        AccountInfoVO traderAccountInfoVO = accountInfoMapper.selectAccountInfo(uid);
        if (traderAccountInfoVO == null){
            throw new BusinessException("用户不存在");
        }
        BigDecimal pointBalance = traderAccountInfoVO.getPointBalance();
        BigDecimal frozenBalance = traderAccountInfoVO.getFrozenBalance();
        if (frozenBalance.compareTo(amount) < 0) {
            throw new BusinessException("insufficient_balance");
        }
        //用户减少冻结余额
        int update = accountInfoMapper.update(null, new LambdaUpdateWrapper<AccountInfo>()
                .eq(AccountInfo::getUid, uid)
                .setSql("point_balance = point_balance - " + amount)
                .setSql("frozen_balance = frozen_balance -" + amount)
                .set(AccountInfo::getUpdateTime, new Date()));
        if (update <= 0) {
            throw new BusinessException("frozen_points_balance_decrease_failed");
        }
        return pointBalance;
    }

    @Transactional
    @Override
    public Boolean unfreezePoints(String uid, BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("amount_must_be_greater_than_zero");
        }
        AccountInfoVO traderAccountInfoVO = accountInfoMapper.selectAccountInfo(uid);
        if (traderAccountInfoVO == null){
            throw new BusinessException("用户不存在");
        }
        if (traderAccountInfoVO.getFrozenBalance().compareTo(amount) < 0) {
            throw new BusinessException("insufficient_frozen_points_balance");
        }
        //兑现冻结积分
        int update = accountInfoMapper.update(null, new LambdaUpdateWrapper<AccountInfo>()
                .eq(AccountInfo::getUid, uid)
                .setSql("available_balance = available_balance + " + amount)
                .setSql("frozen_balance = frozen_balance -" + amount)
                .set(AccountInfo::getUpdateTime, new Date()));
        if (update <= 0) {
            throw new BusinessException("frozen_points_cashout_failed");
        }
        return true;
    }
}
